﻿using System;
using System.ComponentModel;
using Microsoft.VisualStudio.TestTools.WebTesting;
using Microsoft.VisualStudio.TestTools.WebTesting.Rules;

namespace WebAndLoadTestPluginsAndRules.RecorderPlugins
{
    /// <summary>
    /// This class searches for a page title on each page, and if found adds a validation rule to ensure the
    /// page being returned is the expected page.
    /// </summary>
    [DisplayName("Adds title validation rule")]
    [Description("Adds a validation rule that verifies the recorded title tag matches playback title tag value. This helps ensure the returned page is the expected page.")]
    public class AddPageTitleValidation : WebTestRecorderPlugin
    {
        public override void PostWebTestRecording(object sender, PostWebTestRecordingEventArgs e)
        {
            WebTestResultIteration recordedIteration = e.RecordedWebTestResult;
            foreach (WebTestResultUnit resultUnit in recordedIteration.Children)
            {
                WebTestResultPage pageResult = resultUnit as WebTestResultPage;
                if (pageResult == null)
                {
                    continue;
                }

                WebTestRequestResult finalRequestResult = pageResult.RequestResult;

                //if there were redirects then need to get the last redirected requests
                if (pageResult.RedirectedPages.Count > 0)
                {
                    finalRequestResult = pageResult.RedirectedPages[pageResult.RedirectedPages.Count - 1].RequestResult;
                }

                //now get the response for the final request
                WebTestResponse response = finalRequestResult.Response;
                if (!response.IsHtml)
                {
                    continue;
                }

                //search for the <title> tag
                HtmlTagInnerTextParser innerTextParser = new HtmlTagInnerTextParser(response.BodyString);
                HtmlTagInnerText titleInnerTextTag = null;

                foreach (HtmlTagInnerText innerTextTag in 
                            innerTextParser.GetInnerTextForHtmlTags("title", true, false, false))
                {
                    if (!string.IsNullOrEmpty(innerTextTag.Value))
                    {
                        titleInnerTextTag = innerTextTag;
                        break;
                    }
                }

                if (titleInnerTextTag == null)
                {
                    continue;
                }

                //if we found a title tag then add a validation rule
                ValidationRuleReference validateTitleRuleReference = new ValidationRuleReference();
                validateTitleRuleReference.Type = typeof(ValidateHtmlTagInnerText);
                validateTitleRuleReference.ValidationLevel = ValidationLevel.Medium;
                validateTitleRuleReference.Properties.Add(new PluginOrRuleProperty("TagName", "title"));
                validateTitleRuleReference.Properties.Add(new PluginOrRuleProperty("ExpectedInnerText", 
                                                                                    titleInnerTextTag.Value));
                validateTitleRuleReference.Properties.Add(new PluginOrRuleProperty("Index", "0"));
                validateTitleRuleReference.Properties.Add(new PluginOrRuleProperty("RemoveInnerTags", "False"));
                validateTitleRuleReference.Properties.Add(new PluginOrRuleProperty("HasClosingTags", "True"));
                validateTitleRuleReference.Properties.Add(new PluginOrRuleProperty("IgnoreCase", "True"));
                validateTitleRuleReference.Properties.Add(new PluginOrRuleProperty("CollapseWhiteSpace",                                                                                            "False"));

                // Get the corresponding request in the Declarative Web test
                WebTestRequest requestInWebTest = 
                        e.RecordedWebTest.GetItem(pageResult.DeclarativeWebTestItemId) as WebTestRequest;
                if (requestInWebTest != null)
                {
                    requestInWebTest.ValidationRuleReferences.Add(validateTitleRuleReference);
                    e.RecordedWebTestModified = true;
                }
            }
        }
    }
}